package com.tarena.demo.luban.all.main.consumer;

import com.tarena.demo.luban.all.main.service.OrderService;
import com.tarena.demo.luban.commons.exception.BusinessDemoException;
import com.tarena.demo.luban.protocol.order.param.OrderAddParam;
import org.apache.commons.lang.StringUtils;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Component
@RocketMQMessageListener(topic="order-add-topic",consumerGroup = "${rocketmq.consumer.group}")
public class OrderAddConsumer implements RocketMQListener<OrderAddParam> {
    @Autowired
    private OrderService orderService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public void onMessage(OrderAddParam message) {
        String randCode=new Random().nextInt(9000)+1000+"";
        String lockKey="order:add:lock:"+message.getOrderSn();
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        //setnx key value key设计思路 前缀(对业务的描述)+业务数据+后缀(key特性 作用) tea:mall:goods:{goodId}
        Boolean tryLock = opsForValue.setIfAbsent(
                lockKey, randCode, 10, TimeUnit.SECONDS);
        try {
            int count=0;
            int initTime=5000;
            while (!tryLock) {
                //最多抢三次 三次都没抢到 不在执行业务
                //TODO 每多抢一次,稍等1秒钟
                if (count>=3){
                    return;
                }
                count++;
                Thread.sleep(initTime);
                //给tryLock重新赋值
                tryLock = opsForValue.setIfAbsent(
                        lockKey, randCode, 10, TimeUnit.SECONDS);
            }
            orderService.addOrder(message);
        }catch (InterruptedException e){
            //TODO 处理逻辑
        }finally {
            //finally手动释放最合适
            //查询 锁的value值
            String randValue = opsForValue.get(lockKey);
            if (StringUtils.isNotEmpty(randValue) && randValue.equals(randCode)){
                //只有从redis读到了锁的value并且等于当前线程的随机数,才删除
                redisTemplate.delete(lockKey);
            }
        }
    }
}
